package com.cicc.beergamevirtualsimulationsystem.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cicc.beergamevirtualsimulationsystem.common.constant.RecordConstant;
import com.cicc.beergamevirtualsimulationsystem.common.enums.RecordEnum.CapacityEnum;
import com.cicc.beergamevirtualsimulationsystem.common.enums.RecordEnum.DeliverStatus;
import com.cicc.beergamevirtualsimulationsystem.common.enums.RecordEnum.OrderGoodsStatus;
import com.cicc.beergamevirtualsimulationsystem.common.enums.userTypeEnum.RoleType;
import com.cicc.beergamevirtualsimulationsystem.common.errorEnum.RecordErrorEnum;
import com.cicc.beergamevirtualsimulationsystem.common.exception.ExceptionFactory;
import com.cicc.beergamevirtualsimulationsystem.entity.RecordDetailEntity;
import com.cicc.beergamevirtualsimulationsystem.entity.RecordEntity;
import com.cicc.beergamevirtualsimulationsystem.entity.RoleBindingEntity;
import com.cicc.beergamevirtualsimulationsystem.entity.RoomInfoManager;
import com.cicc.beergamevirtualsimulationsystem.mapper.ParameterMapper;
import com.cicc.beergamevirtualsimulationsystem.mapper.RecordMapper;
import com.cicc.beergamevirtualsimulationsystem.mapper.RoleBindingMapper;
import com.cicc.beergamevirtualsimulationsystem.mapper.RoleTypeMapper;
import com.cicc.beergamevirtualsimulationsystem.model.parameter.dto.RoomParameterDto;
import com.cicc.beergamevirtualsimulationsystem.model.record.vo.RecordQueryVO;
import com.cicc.beergamevirtualsimulationsystem.model.userType.RoleTypeParameterDto;
import com.cicc.beergamevirtualsimulationsystem.service.ParameterService;
import com.cicc.beergamevirtualsimulationsystem.service.RecordDetailService;
import com.cicc.beergamevirtualsimulationsystem.service.RecordService;
import com.cicc.beergamevirtualsimulationsystem.service.recordInit.BaseRecordInit;
import com.cicc.beergamevirtualsimulationsystem.service.recordInit.RecordDTO;
import com.cicc.beergamevirtualsimulationsystem.service.recordInit.RecordInitHolder;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class RecordServiceImpl extends ServiceImpl<RecordMapper, RecordEntity> implements RecordService {
    @Resource
    private RoleBindingMapper roleBindingMapper;
    @Resource
    private RoleTypeMapper roleTypeMapper;
    @Resource
    private RecordDetailService recordDetailService;
    @Resource
    private ParameterMapper parameterMapper;
    @Resource
    private ParameterService parameterService;

    @Resource
    private RecordInitHolder recordInitHolder;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initRecord(String roomId, Integer period, Integer orderNum) {
        // 判断当前房间下该周期记录是否存在
        if (existRecord(roomId, period)) {
            throw ExceptionFactory.bizException(RecordErrorEnum.PERIOD_RECORD_NOT_NULL_ERROR.getCode(), RecordErrorEnum.PERIOD_RECORD_NOT_NULL_ERROR.getMsg());
        }

        // 获取房间参数
        RoomParameterDto roomParameterDto = parameterService.queryParameterByRoomId(roomId);
        Integer cycles = roomParameterDto.getCurrentRoomParameter().getCycles();
        Integer deliveryCycle = roomParameterDto.getCurrentRoomParameter().getDeliveryCycle();
        Map<Integer, Integer> paramMap = roomParameterDto.getRoleTypeParameterList().stream().collect(Collectors.toMap(RoleTypeParameterDto::getRoleType, RoleTypeParameterDto::getOpeningInventory));
        if (cycles < period) {
            return;
        }

        // 获取当前房间id下所有玩家
        LambdaQueryWrapper<RoleBindingEntity> RoleBindingQueryWrapper = new LambdaQueryWrapper<>();
        RoleBindingQueryWrapper.eq(RoleBindingEntity::getRoomId, roomId);
        List<RoleBindingEntity> roleBindingEntities = roleBindingMapper.selectList(RoleBindingQueryWrapper);
        Map<String, RoleBindingEntity> roleBindingEntityMap = roleBindingEntities.stream().collect(Collectors.toMap(RoleBindingEntity::getUserId, data -> data));
        roleBindingEntities = roleBindingEntities.stream().filter(data -> !data.getRoleType().equals(RoleType.CUSTOMER.getCode())).toList();

        // 上1周所有用户记录
        List<RecordEntity> recordEntitiesOne = recordList(period - 1, roomId);
        Map<String, RecordEntity> recordEntityMapOne = recordEntitiesOne.stream().collect(Collectors.toMap(RecordEntity::getUserId, data -> data));
        // 上n周所有用户记录
        List<RecordEntity> recordEntitiesN = recordList(period - deliveryCycle, roomId);
        Map<String, RecordEntity> recordEntityMapN = recordEntitiesN.stream().collect(Collectors.toMap(RecordEntity::getUserId, data -> data));
        // 上1周所有用户记录明细
        List<RecordDetailEntity> recordDetailEntitiesOne = recordDetailList(recordEntitiesOne);
        Map<String, RecordDetailEntity> recordDetailEntityMapOne = recordDetailEntitiesOne.stream().collect(Collectors.toMap(key -> key.getUserId() + key.getDownStreamId(), data -> data));
        // 上n周所有用户记录明细
        List<RecordDetailEntity> recordDetailEntitiesN = recordDetailList(recordEntitiesN);
        Map<String, RecordDetailEntity> recordDetailEntityMapN = recordDetailEntitiesN.stream().filter(data -> !(data.getDownStreamRole() == RoleType.CUSTOMER.getCode())).collect(Collectors.toMap(RecordDetailEntity::getDownStreamId, data -> data));

        List<RecordEntity> recordResult = new ArrayList<>();

        Map<String, List<RecordDetailEntity>> recordDetailResultMap = new HashMap<>();
        for (RoleBindingEntity roleBindingEntity : roleBindingEntities) {
            Integer orderTotal = 0;
            // 初始化记录明细
            List<RecordDetailEntity> recordDetailEntities = new ArrayList<>();
            List<Object> downStreamIds = JSONUtil.parseArray(roleBindingEntity.getDownStreamIds()).stream().toList();
            for (Object downStreamId : downStreamIds) {
                String userName = roleBindingEntityMap.get(roleBindingEntity.getUserId()).getRoleName();
                String downStreamName = roleBindingEntityMap.get(downStreamId).getRoleName();
                Integer userRole = roleBindingEntityMap.get(downStreamId).getRoleType();
                // 订单量 = 前n周该下游的订货量
                Integer order = ObjUtil.isNotNull(recordEntityMapN.get(downStreamId)) ? recordEntityMapN.get(downStreamId).getPreReceiverTotal() : RecordConstant.NUM_MIN;
                // 累计欠货量 = 上1周对该下游的累计欠货量 + 订单量(order 通过前n周数据获取)
                Integer accumulateOweQuantity = ObjUtil.isNotNull(recordDetailEntityMapOne.get(roleBindingEntity.getUserId() + downStreamId)) ? recordDetailEntityMapOne.get(roleBindingEntity.getUserId() + downStreamId).getAccumulateOweQuantity() + order : RecordConstant.NUM_MIN;
                // 零售的订单量来自主持人输入,因此 累计欠货量 = 上1周对该下游的累计欠货量 + 订单量(orderNum 主持人输入)
                if (roleBindingEntity.getRoleType().equals(RoleType.RETAILER.getCode())) {
                    accumulateOweQuantity += orderNum;
                    order = orderNum;
                }
                // 订单总量
                orderTotal += order;

                RecordDetailEntity recordDetailEntity = new RecordDetailEntity();
                recordDetailEntity.setPeriod(period);
                recordDetailEntity.setUserId(roleBindingEntity.getUserId());
                recordDetailEntity.setDownStreamId((String) downStreamId);
                recordDetailEntity.setDownStreamRole(userRole);
                recordDetailEntity.setReceivingCycle(period + deliveryCycle);
                recordDetailEntity.setOrderQuantity(order);
                recordDetailEntity.setAccumulateOweQuantity(accumulateOweQuantity);
                recordDetailEntity.setOweQuantity(order);
                recordDetailEntity.setUserName(userName);
                recordDetailEntity.setDownStreamName(downStreamName);
                recordDetailEntity.setIsDeliver(DeliverStatus.NOT_DELIVER.getCode());
                recordDetailEntities.add(recordDetailEntity);
            }
            recordDetailResultMap.put(roleBindingEntity.getUserId(), recordDetailEntities);
            // 初始化记录
            // 累计欠货总量 = 上1周累计欠货总量 + 本周订单总量
            Integer accumulateOweTotal = ObjUtil.isNotNull(recordEntityMapOne.get(roleBindingEntity.getUserId())) ? recordEntityMapOne.get(roleBindingEntity.getUserId()).getAccumulateOweTotal() + orderTotal : orderTotal;
            // 上游本期欠货量 = 上n周订单中上游对我的欠货量
            Integer upStreamOweTotal = ObjUtil.isNotNull(recordDetailEntityMapN.get(roleBindingEntity.getUserId())) ? recordDetailEntityMapN.get(roleBindingEntity.getUserId()).getOweQuantity() : RecordConstant.NUM_MIN;
            // 收货量：工厂 = 上n周计划生产量  其他 = 上n周订单中上游对我的发货量
            Integer receiverTotal;
            if (roleBindingEntity.getRoleType().equals(RoleType.FACTORY.getCode())) {
                receiverTotal = ObjUtil.isNotNull(recordEntityMapN.get(roleBindingEntity.getUserId())) ? recordEntityMapN.get(roleBindingEntity.getUserId()).getPreReceiverTotal() : RecordConstant.NUM_MIN;
            } else {
                receiverTotal = ObjUtil.isNotNull(recordDetailEntityMapN.get(roleBindingEntity.getUserId())) ? recordDetailEntityMapN.get(roleBindingEntity.getUserId()).getDeliverQuantity() : RecordConstant.NUM_MIN;
            }
            // 期初库存：第1周从参数配置里获取  其他：上1周期末库存 + 本周收货量
            Integer OpeningInventory = period == 1 ? paramMap.get(roleBindingEntity.getRoleType()) : recordEntityMapOne.get(roleBindingEntity.getUserId()).getEndingInventory() + receiverTotal;
            // 上游累计欠货量 = 上1周上游对我的累计欠货量 - 本期收货量
            Integer upStreamAccumulateOweTotal = ObjUtil.isNotNull(recordEntityMapOne.get(roleBindingEntity.getUserId())) ? recordEntityMapOne.get(roleBindingEntity.getUserId()).getUpStreamAccumulateOweTotal() - receiverTotal : RecordConstant.NUM_MIN;
            // 资产 = 上1周资产 第1周为0
            Integer asset = ObjUtil.isNotNull(recordEntityMapOne.get(roleBindingEntity.getUserId())) ? recordEntityMapOne.get(roleBindingEntity.getUserId()).getAsset() : RecordConstant.NUM_MIN;
            String userName = roleBindingEntityMap.get(roleBindingEntity.getUserId()).getRoleName();
            String upStreamName = roleBindingEntity.getRoleType() == RoleType.FACTORY.getCode() ? RecordConstant.FACTORY_NAME : roleBindingEntityMap.get(roleBindingEntity.getUpStreamId()).getRoleName();
            // 工厂产能 = 上1周产能级别 第1周为0级
            Integer capacity = ObjUtil.isNotNull(recordEntityMapOne.get(roleBindingEntity.getUserId())) ? recordEntityMapOne.get(roleBindingEntity.getUserId()).getCapacity() : CapacityEnum.LEVEL_ZERO.getCode();

            RecordEntity recordEntity = new RecordEntity();
            recordEntity.setRoomId(roomId);
            recordEntity.setUserId(roleBindingEntity.getUserId());
            recordEntity.setUserRole(roleBindingEntity.getRoleType());
            recordEntity.setPeriod(period);
            recordEntity.setOrderTotal(orderTotal);
            recordEntity.setAccumulateOweTotal(accumulateOweTotal);
            recordEntity.setReceiverTotal(receiverTotal);
            recordEntity.setOpeningInventory(OpeningInventory);
            recordEntity.setEndingInventory(OpeningInventory);
            recordEntity.setUpStreamOweTotal(upStreamOweTotal);
            recordEntity.setUpStreamAccumulateOweTotal(upStreamAccumulateOweTotal);
            recordEntity.setAsset(asset);
            recordEntity.setOweTotal(orderTotal);
            recordEntity.setUserName(userName);
            recordEntity.setUpStreamId(roleBindingEntity.getUpStreamId());
            recordEntity.setUpStreamName(upStreamName);
            recordEntity.setIsOrderGoods(OrderGoodsStatus.NOT_ORDER_GOODS.getCode());
            if (roleBindingEntity.getRoleType() == RoleType.FACTORY.getCode()) {
                recordEntity.setCapacity(capacity);
            }
            recordResult.add(recordEntity);
        }
        // 插入数据库
        this.saveBatch(recordResult);
        ArrayList<RecordDetailEntity> recordDetailResult = new ArrayList<>();
        for (RecordEntity recordEntity : recordResult) {
            List<RecordDetailEntity> list = recordDetailResultMap.get(recordEntity.getUserId()).stream().peek(data -> data.setRecordId(recordEntity.getId())).toList();
            recordDetailResult.addAll(list);
        }
        recordDetailService.saveBatch(recordDetailResult);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initRecordTest(String roomId, Integer period, Integer orderNum) {
        // 判断当前房间下该周期记录是否存在
        if (existRecord(roomId, period)) {
            throw ExceptionFactory.bizException(RecordErrorEnum.PERIOD_RECORD_NOT_NULL_ERROR.getCode(), RecordErrorEnum.PERIOD_RECORD_NOT_NULL_ERROR.getMsg());
        }
        // 获取房间参数
        RoomParameterDto roomParameterDto = parameterService.queryParameterByRoomId(roomId);
        Integer cycles = roomParameterDto.getCurrentRoomParameter().getCycles();
        Integer deliveryCycle = roomParameterDto.getCurrentRoomParameter().getDeliveryCycle();
        Map<Integer, Integer> paramMap = roomParameterDto.getRoleTypeParameterList().stream().collect(Collectors.toMap(RoleTypeParameterDto::getRoleType, RoleTypeParameterDto::getOpeningInventory));
        if (cycles < period) {
            return;
        }
        // 获取当前房间id下所有玩家
        LambdaQueryWrapper<RoleBindingEntity> RoleBindingQueryWrapper = new LambdaQueryWrapper<>();
        RoleBindingQueryWrapper.eq(RoleBindingEntity::getRoomId, roomId);
        List<RoleBindingEntity> roleBindingEntities = roleBindingMapper.selectList(RoleBindingQueryWrapper);
        Map<String, RoleBindingEntity> roleBindingEntityMap = roleBindingEntities.stream().collect(Collectors.toMap(RoleBindingEntity::getUserId, data -> data));

        // 上1周所有用户记录
        List<RecordEntity> recordEntitiesOne = recordList(period - 1, roomId);
        Map<String, RecordEntity> recordEntityMapOne = recordEntitiesOne.stream().collect(Collectors.toMap(RecordEntity::getUserId, data -> data));
        // 上n周所有用户记录
        List<RecordEntity> recordEntitiesN = recordList(period - deliveryCycle, roomId);
        Map<String, RecordEntity> recordEntityMapN = recordEntitiesN.stream().collect(Collectors.toMap(RecordEntity::getUserId, data -> data));
        // 上1周所有用户记录明细
        List<RecordDetailEntity> recordDetailEntitiesOne = recordDetailList(recordEntitiesOne);
        Map<String, RecordDetailEntity> recordDetailEntityMapOne = recordDetailEntitiesOne.stream().collect(Collectors.toMap(key -> key.getUserId() + key.getDownStreamId(), data -> data));
        // 上n周所有用户记录明细
        List<RecordDetailEntity> recordDetailEntitiesN = recordDetailList(recordEntitiesN);
        Map<String, RecordDetailEntity> recordDetailEntityMapN = recordDetailEntitiesN.stream().filter(data -> !(data.getDownStreamRole() == RoleType.CUSTOMER.getCode())).collect(Collectors.toMap(RecordDetailEntity::getDownStreamId, data -> data));

        List<RecordEntity> recordResult = new ArrayList<>();
        Map<String, List<RecordDetailEntity>> recordDetailResultMap = new HashMap<>();
        recordInitHolder.init(roomId, period, deliveryCycle, paramMap, recordEntityMapOne, recordEntityMapN, recordDetailEntityMapOne, recordDetailEntityMapN, roleBindingEntityMap);
        for (RoleBindingEntity roleBindingEntity : roleBindingEntities) {
            BaseRecordInit recordInit = recordInitHolder.getRecordInit(roleBindingEntity.getRoleType());
            RecordDTO recordDTO = recordInit.init(roleBindingEntity, orderNum);
            recordResult.add(recordDTO.getRecordEntity());
            recordDetailResultMap.put(recordDTO.getRecordEntity().getUserId(), recordDTO.getRecordDetailEntityList());
        }
        // 插入数据库
        this.saveBatch(recordResult);
        ArrayList<RecordDetailEntity> recordDetailResult = new ArrayList<>();
        for (RecordEntity recordEntity : recordResult) {
            List<RecordDetailEntity> list = recordDetailResultMap.get(recordEntity.getUserId()).stream().peek(data -> data.setRecordId(recordEntity.getId())).toList();
            recordDetailResult.addAll(list);
        }
        recordDetailService.saveBatch(recordDetailResult);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RecordQueryVO upgradeCapacity(String recordId) {
        // 获取周期记录
        RecordEntity record = existRecord(recordId);
        // 判断是否为工厂
        if (record.getUserRole() != RoleType.FACTORY.getCode()) {
            throw ExceptionFactory.bizException(RecordErrorEnum.NOT_FACTORY_ERROR.getCode(), RecordErrorEnum.NOT_FACTORY_ERROR.getMsg());
        }
        // 判断产能级别是否为最高级
        Integer maxCapacity = CapacityEnum.maxCapacity();
        if (record.getCapacity() == maxCapacity) {
            throw ExceptionFactory.bizException(RecordErrorEnum.CAPACITY_MAX_ERROR.getCode(), RecordErrorEnum.CAPACITY_MAX_ERROR.getMsg());
        }
        // 升级
        record.setCapacity(record.getCapacity() + 1);

        this.updateById(record);

        return queryRecord(record.getRoomId(), record.getUserId());
    }

    /**
     * 查询主持人的下单记录
     */
    @Override
    public Integer queryHostOrder(String roomId) {
        return RoomInfoManager.getCustomerOrder(roomId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RecordQueryVO orderGoods(String recordId, Integer orderNum) {
        // 获取周期记录
        RecordEntity record = existRecord(recordId);
        // 判断是否已订货
        if (record.getIsOrderGoods() == OrderGoodsStatus.ORDER_GOODS.getCode()) {
            throw ExceptionFactory.bizException(RecordErrorEnum.IS_ORDER_GOODS_ERROR.getCode(), RecordErrorEnum.IS_ORDER_GOODS_ERROR.getMsg());
        }
        // 工厂：判断产能级别
        if (record.getUserRole() == RoleType.FACTORY.getCode()) {
            Integer capacityMin = record.getCapacity() * CapacityEnum.CAPACITY_NUM;
            Integer capacityMax = (record.getCapacity() + 1) * CapacityEnum.CAPACITY_NUM;
            if (orderNum < capacityMin || orderNum > capacityMax) {
                throw ExceptionFactory.bizException(RecordErrorEnum.CAPACITY_LEVEL_ERROR.getCode(), RecordErrorEnum.CAPACITY_LEVEL_ERROR.getMsg());
            }
        }
        record.setPreReceiverTotal(orderNum);
        record.setIsOrderGoods(OrderGoodsStatus.ORDER_GOODS.getCode());
        record.setUpStreamAccumulateOweTotal(record.getUpStreamAccumulateOweTotal() + orderNum);
        this.updateById(record);

        return queryRecord(record.getRoomId(), record.getUserId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RecordQueryVO deliverGoods(String recordDetailId, Integer deliverNum) {
        // 判断记录明细是否存在
        LambdaQueryWrapper<RecordDetailEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordDetailEntity::getId, recordDetailId);
        RecordDetailEntity recordDetailEntity = recordDetailService.getOne(queryWrapper);
        if (ObjUtil.isNull(recordDetailEntity)) {
            throw ExceptionFactory.bizException(RecordErrorEnum.PERIOD_RECORD_DETAIL_NULL_ERROR.getCode(), RecordErrorEnum.PERIOD_RECORD_DETAIL_NULL_ERROR.getMsg());
        }
        // 判断是否已发货
        if (recordDetailEntity.getIsDeliver() == DeliverStatus.DELIVER.getCode()) {
            throw ExceptionFactory.bizException(RecordErrorEnum.IS_DELIVER_ERROR.getCode(), RecordErrorEnum.IS_DELIVER_ERROR.getMsg());
        }
        // 获取关联记录
        RecordEntity recordEntity = this.getById(recordDetailEntity.getRecordId());
        if (ObjUtil.isNull(recordEntity)) {
            throw ExceptionFactory.bizException(RecordErrorEnum.PERIOD_RECORD_NULL_ERROR.getCode(), RecordErrorEnum.PERIOD_RECORD_NULL_ERROR.getMsg());
        }

        if (deliverNum > recordEntity.getEndingInventory()) {
            throw ExceptionFactory.bizException(RecordErrorEnum.DELIVER_QUANTITY_GT_INVENTORY_ERROR.getCode(), RecordErrorEnum.DELIVER_QUANTITY_GT_INVENTORY_ERROR.getMsg());
        }
        if (deliverNum > recordDetailEntity.getAccumulateOweQuantity()) {
            throw ExceptionFactory.bizException(RecordErrorEnum.DELIVER_QUANTITY_GT_ACCUMULATE_OWE_QUANTITY_ERROR.getCode(), RecordErrorEnum.DELIVER_QUANTITY_GT_ACCUMULATE_OWE_QUANTITY_ERROR.getMsg());
        }
        // 更新记录明细
        recordDetailEntity.setDeliverQuantity(deliverNum);
        recordDetailEntity.setOweQuantity(deliverNum <= recordDetailEntity.getOrderQuantity() ? recordDetailEntity.getOweQuantity() - deliverNum : RecordConstant.NUM_MIN);
        recordDetailEntity.setAccumulateOweQuantity(recordDetailEntity.getAccumulateOweQuantity() - deliverNum);
        recordDetailEntity.setIsDeliver(DeliverStatus.DELIVER.getCode());

        Integer oweOffset = recordDetailEntity.getOrderQuantity() > deliverNum ? deliverNum : recordDetailEntity.getOrderQuantity();
        // 更新记录
        recordEntity.setDeliverTotal(recordEntity.getDeliverTotal() + deliverNum);
        recordEntity.setOweTotal(recordEntity.getOweTotal() - oweOffset);
        recordEntity.setAccumulateOweTotal(recordEntity.getAccumulateOweTotal() - deliverNum);
        recordEntity.setEndingInventory(recordEntity.getEndingInventory() - deliverNum);

        this.updateById(recordEntity);
        recordDetailService.updateById(recordDetailEntity);

        return queryRecord(recordEntity.getRoomId(), recordEntity.getUserId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RecordQueryVO oneClickDeliver(String recordId) {
        // 获取周期记录
        RecordEntity recordEntity = existRecord(recordId);
        // 获取记录明细 并过滤掉已发货的下游
        List<RecordDetailEntity> recordDetailEntities = recordDetailList(List.of(recordEntity)).stream().filter(data -> data.getIsDeliver() == DeliverStatus.NOT_DELIVER.getCode()).toList();
        if (CollUtil.isEmpty(recordDetailEntities)) {
            throw ExceptionFactory.bizException(RecordErrorEnum.IS_DELIVER_ERROR.getCode(), RecordErrorEnum.IS_DELIVER_ERROR.getMsg());
        }
        // 判断库存是否充足
        int sum = recordDetailEntities.stream().mapToInt(RecordDetailEntity::getAccumulateOweQuantity).sum();
        if (sum > recordEntity.getEndingInventory()) {
            // 库存不足改为 平均发货
            /*averageDeliver(recordId);
            return;*/
            throw ExceptionFactory.bizException(RecordErrorEnum.DELIVER_QUANTITY_GT_INVENTORY_ERROR.getCode(), RecordErrorEnum.DELIVER_QUANTITY_GT_INVENTORY_ERROR.getMsg());
        }

        int oweTotal = recordDetailEntities.stream().mapToInt(RecordDetailEntity::getOweQuantity).sum();
        // 更新记录明细
        for (RecordDetailEntity recordDetailEntity : recordDetailEntities) {
            recordDetailEntity.setDeliverQuantity(recordDetailEntity.getAccumulateOweQuantity());
            recordDetailEntity.setOweQuantity(RecordConstant.NUM_MIN);
            recordDetailEntity.setAccumulateOweQuantity(RecordConstant.NUM_MIN);
            recordDetailEntity.setIsDeliver(DeliverStatus.DELIVER.getCode());
        }
        // 更新记录
        recordEntity.setDeliverTotal(recordEntity.getDeliverTotal() + sum);
        recordEntity.setOweTotal(recordEntity.getOweTotal() - oweTotal);
        recordEntity.setAccumulateOweTotal(recordEntity.getAccumulateOweTotal() - sum);
        recordEntity.setEndingInventory(recordEntity.getEndingInventory() - sum);

        this.updateById(recordEntity);
        recordDetailService.updateBatchById(recordDetailEntities);

        return queryRecord(recordEntity.getRoomId(), recordEntity.getUserId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RecordQueryVO averageDeliver(String recordId) {
        // 获取周期记录
        RecordEntity recordEntity = existRecord(recordId);
        // 获取记录明细 并过滤掉已发货的下游
        List<RecordDetailEntity> recordDetailEntities = recordDetailList(List.of(recordEntity)).stream().filter(data -> data.getIsDeliver() == DeliverStatus.NOT_DELIVER.getCode()).toList();
        if (CollUtil.isEmpty(recordDetailEntities)) {
            throw ExceptionFactory.bizException(RecordErrorEnum.IS_DELIVER_ERROR.getCode(), RecordErrorEnum.IS_DELIVER_ERROR.getMsg());
        }
        // 获取平均发货量
        Integer averageNum = recordEntity.getEndingInventory() / recordDetailEntities.size();
        // 判断发货量是否为0
        if (recordEntity.getEndingInventory() > RecordConstant.NUM_MIN && averageNum == RecordConstant.NUM_MIN) {
            throw ExceptionFactory.bizException(RecordErrorEnum.DELIVER_QUANTITY_ZERO_ERROR.getCode(), RecordErrorEnum.DELIVER_QUANTITY_ZERO_ERROR.getMsg());
        }

        Integer deliverTotal = 0;
        Integer oweOffset = 0;
        // 更新记录明细
        for (RecordDetailEntity recordDetailEntity : recordDetailEntities) {
            Integer deliverNum = averageNum > recordDetailEntity.getAccumulateOweQuantity() ? recordDetailEntity.getAccumulateOweQuantity() : averageNum;
            Integer oweNum = deliverNum > recordDetailEntity.getOweQuantity() ? RecordConstant.NUM_MIN : recordDetailEntity.getOweQuantity() - deliverNum;
            deliverTotal += deliverNum;
            oweOffset += recordDetailEntity.getOrderQuantity() - oweNum;

            recordDetailEntity.setDeliverQuantity(deliverNum);
            recordDetailEntity.setIsDeliver(DeliverStatus.DELIVER.getCode());
            recordDetailEntity.setOweQuantity(oweNum);
            recordDetailEntity.setAccumulateOweQuantity(recordDetailEntity.getAccumulateOweQuantity() - deliverNum);
        }

        // 更新记录
        recordEntity.setOweTotal(recordEntity.getOweTotal() - oweOffset);
        recordEntity.setDeliverTotal(deliverTotal);
        recordEntity.setAccumulateOweTotal(recordEntity.getAccumulateOweTotal() - deliverTotal);
        recordEntity.setEndingInventory(recordEntity.getEndingInventory() - deliverTotal);

        this.updateById(recordEntity);
        recordDetailService.updateBatchById(recordDetailEntities);

        return queryRecord(recordEntity.getRoomId(), recordEntity.getUserId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void settle(String roomId, Integer period) {
        // 获取并判断周期记录是否存在
        LambdaQueryWrapper<RecordEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordEntity::getRoomId, roomId);
        queryWrapper.eq(RecordEntity::getPeriod, period);
        List<RecordEntity> recordEntities = this.list(queryWrapper);
        // TODO: 判断

        // 获取所有角色相关参数
        Map<Integer, RoleTypeParameterDto> roleTypeEntityMap = parameterService.queryParameterByRoomId(roomId).getRoleTypeParameterList().stream().collect(Collectors.toMap(RoleTypeParameterDto::getRoleType, data -> data));
        for (RecordEntity recordEntity : recordEntities) {
            // 角色参数
            RoleTypeParameterDto roleType = roleTypeEntityMap.get(recordEntity.getUserRole());
            // 库存成本
            Integer inventoryPrice = recordEntity.getEndingInventory() * roleType.getInventoryUnitPrice();
            // 延期交付成本
            Integer delayedDeliveryPrice = recordEntity.getAccumulateOweTotal() * roleType.getDelayedDeliveryUnitPrice();
            // 订货/生产成本
            Integer purchasePrice = recordEntity.getPreReceiverTotal() * roleType.getPurchasePrice();
            // 本期利润
            Integer profit = (recordEntity.getDeliverTotal() * roleType.getSellingPrice()) - inventoryPrice - delayedDeliveryPrice - purchasePrice;
            // 当前资产
            Integer asset = recordEntity.getAsset() + profit;

            recordEntity.setInventoryCost(inventoryPrice);
            recordEntity.setDeferredDeliveryCost(delayedDeliveryPrice);
            recordEntity.setPreReceiverTotalCost(purchasePrice);
            recordEntity.setProfit(profit);
            recordEntity.setAsset(asset);
        }
        this.updateBatchById(recordEntities);
    }

    @Override
    public RecordQueryVO queryRecord(String roomId, String userId) {
        RecordQueryVO recordQueryVO = new RecordQueryVO();
        // 获取最新周期记录
        LambdaQueryWrapper<RecordEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordEntity::getRoomId, roomId);
        queryWrapper.eq(RecordEntity::getUserId, userId);
        // queryWrapper.eq(RecordEntity::getPeriod, period);
        queryWrapper.orderByDesc(RecordEntity::getPeriod);
        queryWrapper.last("limit 1");
        RecordEntity recordEntity = this.getOne(queryWrapper);
        if (ObjUtil.isNull(recordEntity)) {
            return recordQueryVO;
        }
        BeanUtil.copyProperties(recordEntity, recordQueryVO);
        // 获取本周期记录明细
        LambdaQueryWrapper<RecordDetailEntity> recordDetailQueryWrapper = new LambdaQueryWrapper<>();
        recordDetailQueryWrapper.eq(RecordDetailEntity::getRecordId, recordEntity.getId());
        recordDetailQueryWrapper.eq(RecordDetailEntity::getPeriod, recordQueryVO.getPeriod());
        List<RecordDetailEntity> recordDetailEntities1 = recordDetailService.list(recordDetailQueryWrapper);
        recordQueryVO.setRecordDetailEntities1(recordDetailEntities1);
        // 设置工厂产能数据
        if (recordQueryVO.getUserRole() == RoleType.FACTORY.getCode()) {
            recordQueryVO.setCapacityCurrentLevel(recordEntity.getCapacity());
            recordQueryVO.setCapacityMaxLevel(CapacityEnum.maxCapacity());
            recordQueryVO.setCapacityMin(recordEntity.getCapacity() * CapacityEnum.CAPACITY_NUM);
            recordQueryVO.setCapacityMax((recordEntity.getCapacity() + 1) * CapacityEnum.CAPACITY_NUM);
        }

        // 获取收货周期为本周期的记录明细
        /*LambdaQueryWrapper<RecordDetailEntity> recordDetailQueryWrapper2 = new LambdaQueryWrapper<>();
        recordDetailQueryWrapper2.eq(RecordDetailEntity::getRecordId, recordEntity.getId());
        recordDetailQueryWrapper2.eq(RecordDetailEntity::getReceivingCycle, period);
        List<RecordDetailEntity> recordDetailEntities2 = recordDetailService.list(recordDetailQueryWrapper2);
        recordQueryVO.setRecordDetailEntities2(recordDetailEntities2);*/
        return recordQueryVO;
    }

    /**
     * 判断当前房间下周期记录是否已存在
     */
    private Boolean existRecord(String roomId, Integer period) {
        LambdaQueryWrapper<RecordEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordEntity::getRoomId, roomId);
        queryWrapper.eq(RecordEntity::getPeriod, period);
        return this.count(queryWrapper) > 0;
    }

    /**
     * 根据周期记录id获取周期记录 并判断是否存在
     */
    private RecordEntity existRecord(String recordId) {
        LambdaQueryWrapper<RecordEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordEntity::getId, recordId);
        RecordEntity record = this.getOne(queryWrapper);
        if (ObjUtil.isNull(record)) {
            throw ExceptionFactory.bizException(RecordErrorEnum.PERIOD_RECORD_NULL_ERROR.getCode(), RecordErrorEnum.PERIOD_RECORD_NULL_ERROR.getMsg());
        }
        return record;
    }

    /**
     * 获取当前房间下所有角色上n周记录
     */
    private List<RecordEntity> recordList(Integer period, String roomId) {
        LambdaQueryWrapper<RecordEntity> recordQueryWrapper = new LambdaQueryWrapper<>();
        recordQueryWrapper.eq(RecordEntity::getRoomId, roomId);
        recordQueryWrapper.eq(RecordEntity::getPeriod, period);
        List<RecordEntity> recordEntities = this.list(recordQueryWrapper);
        return recordEntities;
    }

    /**
     * 获取当前房间下所有角色上n周记录明细
     * TODO 有待优化(参数)
     */
    private List<RecordDetailEntity> recordDetailList(List<RecordEntity> recordEntities) {
        List<RecordDetailEntity> recordDetailEntities = new ArrayList<>();
        if (CollUtil.isEmpty(recordEntities)) {
            return recordDetailEntities;
        }
        List<String> recordIds = recordEntities.stream().map(RecordEntity::getId).collect(Collectors.toList());
        LambdaQueryWrapper<RecordDetailEntity> recordDetailQueryWrapper1 = new LambdaQueryWrapper<>();
        recordDetailQueryWrapper1.in(RecordDetailEntity::getRecordId, recordIds);
        recordDetailEntities = recordDetailService.list(recordDetailQueryWrapper1);
        return recordDetailEntities;
    }
}
